///\todo upgrade

//////////////////////////////////////////////////////////////////////////////////
//                                                                              //
//  This file is part of the buola project (https://code.google.com/p/buola/).  //
//                                                                              //
//  Copyright(c) 2007-2012 Xavi Gratal                                          //
//  gratal AT gmail DOT com                                                     //
//                                                                              //
//  Buola is free software: you can redistribute it and/or modify               //
//  it under the terms of the GNU General Public License as published by        //
//  the Free Software Foundation, either version 3 of the License, or           //
//  (at your option) any later version.                                         //
//                                                                              //
//  Buola is distributed in the hope that it will be useful,                    //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of              //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               //
//  GNU General Public License for more details.                                //
//                                                                              //
//  You should have received a copy of the GNU General Public License           //
//  along with buola.  If not, see <http://www.gnu.org/licenses/>.              //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

#ifndef _BUOLA_BBOX_BSERVICE_H_
#define _BUOLA_BBOX_BSERVICE_H_

#include <buola/bbox/detail/cservicebase.h>
#include <buola/bbox/detail/cintrospection.h>
#include <buola/bbox/detail/clink.h>
#include <buola/bbox/functions.h>

namespace buola { namespace bbox {

template<typename tDerived>
class BService : public detail::CServiceBase
{
protected:
    BService()
    {}

    virtual ~BService()
    {}
    
private:
    ///\todo make it return a packet, which will be sent directly by the daemon
    void BBoxCall(protocol::CPacket &pPacket,protocol::CPacket &pReply) final
    {
        BBoxInitStatic();

        std::string lMethod;
        pPacket >> lMethod;

        auto lIt=mBBoxIntrospection->mMethods.find(lMethod);
                       
        if(lIt!=mBBoxIntrospection->mMethods.end())
        {
            lIt->second->Dispatch(pPacket,pReply,static_cast<tDerived*>(this));
        }
        else
        {
            pReply.Header().SetError(protocol::EError::METHOD_NOT_FOUND);
        }
    }

    void BBoxConnect(protocol::CPacket &pPacket,protocol::CPacket &pReply,const protocol::PPeerConnection &pConnection) final
    {
        BBoxInitStatic();
        
        std::string lTerminal;
        pPacket >> lTerminal;
        uint64_t lRemoteID;
        pPacket >> lRemoteID;
        
        auto lIt=mBBoxIntrospection->mTerminals.find(lTerminal);

        if(lIt!=mBBoxIntrospection->mTerminals.end())
        {
            uint64_t lLocalID=get_new_uid();
            lIt->second->Connect(pConnection,{lLocalID,lRemoteID},static_cast<tDerived*>(this));
            pReply << lLocalID;
        }
        else
        {
            pReply.Header().SetError(protocol::EError::TERMINAL_NOT_FOUND);
        }
    }
    
    static void BBoxInitStatic()
    {
        if(!mBBoxIntrospection)
        {
            mBBoxIntrospection=new detail::CIntrospection<tDerived>;
            tDerived::Introspect(*mBBoxIntrospection);
        }
    }
    
    static detail::CIntrospection<tDerived> *mBBoxIntrospection;
};

template<class tDerived>
detail::CIntrospection<tDerived> *BService<tDerived>::mBBoxIntrospection=nullptr;

///@}
    
/*namespace bbox*/ } /*namespace buola*/ }

#endif
